#pragma once

#include <iostream>
#include <string>
#include <list>
#include <memory>
#include <algorithm>

#include <sys/types.h>
#include <sys/socket.h>

#include "InetAddr.hpp"
#include "Log.hpp"
#include "Mutex.hpp"

using namespace LogModule;
using namespace MutexModule;

class UserInterface
{
public:
    virtual ~UserInterface() = default;
    virtual void SendToClient(int sockfd, const std::string &message) = 0;
    virtual bool operator==(const InetAddr &user) = 0;
    virtual std::string Id() = 0;
};

// User: 描述用户
class User : public UserInterface
{
public:
    User(const InetAddr &id)
        : _id(id)
    {}

    ~User() {}

    void SendToClient(int sockfd, const std::string &message) override
    {
        LOG(LogLevel::DEBUG) << "send message to " << _id.Addr() << " info: " << message;
        ::sendto(sockfd, message.c_str(), message.size(), 0, _id.NetAddr(), _id.NetAddrLen());
    }

    bool operator==(const InetAddr &user) override
    {
        return _id == user;
    }

    std::string Id() override
    {
        return _id.Addr();
    }

private:
    InetAddr _id;
};

// 观察者模式: observer
// UserManage: 将所有的用户管理起来
class UserManage
{
public:
    UserManage() {}
    ~UserManage() {}

    void PrintUser()
    {
        for (auto &user : _online_user)
        {
            LOG(LogLevel::DEBUG) << "在线用户: " << user->Id();
        }
    }

    // 添加用户
    void AddUser(InetAddr &id)
    {
        LockGuard lockguard(_mutex);
        for (auto &user : _online_user)
        {
            if (*user == id)
            {
                LOG(LogLevel::INFO) << id.Addr() << " 用户已存在";
                return;
            }
        }
        LOG(LogLevel::INFO) << "新增该用户: " << id.Addr();
        _online_user.push_back(std::make_shared<User>(id));
        PrintUser();
    }

    // 删除用户
    void DelUser(InetAddr &id)
    {
        // 将该用户移到链表的最后
        auto pos = std::remove_if(_online_user.begin(), _online_user.end(),
                             [&id](std::shared_ptr<UserInterface> &user)
                             { return *user == id; });
        // 删除用户
        _online_user.erase(pos, _online_user.end());
        LOG(LogLevel::INFO) << "删除该用户: " << id.Addr();
        PrintUser();
    }

    // 消息转发给所有用户->交给线程池来完成
    void Route(int sockfd, const std::string &message)
    {
        LockGuard lockguard(_mutex);
        for (auto &user : _online_user)
        {
            user->SendToClient(sockfd, message);
        }
    }

private:
    std::list<std::shared_ptr<UserInterface>> _online_user;
    Mutex _mutex;
};